﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Jayden.Dll.Cards.Poker;
using System.Threading;
using System.Globalization;
using Jayden.Dll.Cards.Poker.Enums;

namespace Jayden.Windows.PokerClient
{
	public partial class PokerClientForm : Form
	{
		private WindowsPokerClient m_Client;
		public PokerTableInfo CashGameInfo;

		public PokerPot Pot;

		public PokerClientForm(WindowsPokerClient client, PokerTableView view)
		{
			m_Client = client;
			InitializeComponent();
			pokerTable.Client = client;
			pokerTable.View = view;
			pokerTable.Form = this;
			pokerTable.ClickSeat += new PokerTableControl.ClickSeatEventHandler(pokerTable_ClickSeat);
			pokerTable.ClickCard += new PokerTableControl.ClickCardEventHandler(pokerTable_ClickCard);
			pokerTable.ClickMySeat += new PokerTableControl.ClickSeatEventHandler(pokerTable_ClickMySeat);
		}
		public PokerClientForm()
		{
			InitializeComponent();
		}

		public PokerTableControl PokerTable { get { return pokerTable; } }

		public bool MustPostBoth;
		public ulong CallAmount;
		public ulong RaiseAmount;
		public ulong AllInAmount;
		public Thread TimerThread;
		public Thread SeatTimerThread;

		public bool AutoWaitBigBlind { get { return cbWait.Checked; } }

		public bool IsAutoFold { get { return cbFold.Checked; } }
		public bool IsAutoCall { get { return cbCall.Checked; } }

		public void SetAutoActionControlVisible(bool visible)
		{
			cbFold.Visible = visible;
			cbCall.Visible = visible;
			Point prevPos = cbCall.Location;
			if(CallAmount > AllInAmount)
				cbCall.Text = "All-In";
			else if (CallAmount > 0)
				cbCall.Text = "Call (" + PokerCurrency.GetCurrency(PokerTable.View.Currency).ToString(CallAmount) + ")";
			else
				cbCall.Text = "Check";
			cbCall.Location = prevPos;
		}

		public void SetRebuyControlVisible(bool visible, bool allowDoubleRebuy = true)
		{
			bLeave.Visible = visible;
			bRebuy.Visible = visible;
			bDoubleRebuy.Visible = visible && allowDoubleRebuy;
		}

		public void SetActionControlVisible(bool visible)
		{
			if (visible)
				SetAutoActionControlVisible(false);
			PokerCurrency currency = PokerCurrency.GetCurrency(pokerTable.View.Currency);
			bFold.Visible = visible;
			bCall.Visible = visible;
			bRaise.Visible = visible;
			tbAmount.Visible = visible;
			tbValue.Visible = visible;
			tbValue.Minimum = (int)(Math.Min(RaiseAmount, AllInAmount));
			tbValue.Maximum = (int)AllInAmount;
			tbValue.TickFrequency = Math.Max((int)PokerTable.View.BigBlind, Math.Max((int)PokerTable.View.Pot / 4, (int)AllInAmount / 4));
			if (CallAmount > 0)
			{
				bCall.Text = "Call (" + currency.ToString(CallAmount) + ")";
				if (CallAmount >= AllInAmount)
				{
					bCall.Text = "All-In";
					tbValue.Visible = false;
					tbAmount.Visible = false;
					bRaise.Visible = false;
				}
			}
			else
			{
				bCall.Text = "Check";
			}
			bRaise.Text = "Raise (" + currency.ToString(RaiseAmount) + ")";
			if(RaiseAmount >= AllInAmount)
			{
				bRaise.Text = "All-In";
				tbValue.Visible= false;
				tbAmount.Visible = false;
			}
			if (visible)
				tbAmount.Text = currency.ToString(RaiseAmount, false);
			if (visible && WindowState == FormWindowState.Minimized)
				WindowState = FormWindowState.Normal;
			TopMost = visible;
			Focus();
			PokerTable.Refresh();
		}
		public void SetShowCardsVisible(bool visible)
		{
			bShows.Visible = visible;
		}
		public void SetShowHideCardsVisible(bool visible)
		{
			bMuck.Visible = visible;
			SetShowCardsVisible(visible);
			if (visible && WindowState == FormWindowState.Minimized)
				WindowState = FormWindowState.Normal;
			TopMost = visible;
			Focus();
			PokerTable.Refresh();
		}
		public bool SitOutVisible { get { return cbSitOut.Visible; } set { cbSitOut.Visible = value; } }

		public ulong GetAmount()
		{
			PokerCurrency currency = PokerCurrency.GetCurrency(pokerTable.View.Currency);
			ulong value = 0;
			if (currency.TryParseAmout(tbAmount.Text, out value))
			{
				if (value < CallAmount)
					return 0;
				if (value < RaiseAmount)
					return CallAmount;
				return value;
			}
			return 0;
		}

		private void bFold_Click(object sender, EventArgs e)
		{
			if(CallAmount == 0)
				m_Client.SendAction(pokerTable.View.TableName, ulong.MaxValue);
			else
				m_Client.SendAction(pokerTable.View.TableName, 0);
			SetActionControlVisible(false);
			if (TimerThread != null)
				TimerThread.Abort();
			PokerTable.MyFoldedCards = PokerTable.View.Seats[PokerTable.Me].Cards;
		}

		private void bCall_Click(object sender, EventArgs e)
		{
			m_Client.SendAction(pokerTable.View.TableName, CallAmount);
			SetActionControlVisible(false);
			if (TimerThread != null)
				TimerThread.Abort();
		}

		private void bRaise_Click(object sender, EventArgs e)
		{
			m_Client.SendAction(pokerTable.View.TableName, GetAmount());
			SetActionControlVisible(false);
			if (TimerThread != null)
				TimerThread.Abort();
		}

		public void WriteLine(string line)
		{
			chat.BeginUpdate();
			chat.Items.Add(line);
			while (chat.Items.Count > 50)
				chat.Items.RemoveAt(0);
			if(!chat.Focused)
				chat.SelectedIndex = chat.Items.Count - 1;
			chat.EndUpdate();
		}

		protected override void OnClosing(CancelEventArgs e)
		{
			base.OnClosing(e);
			if (MessageBox.Show(this, "Are you sure you want to leave the table ?", "Leave table", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.No)
				e.Cancel = true;
		}

		protected override void OnClosed(EventArgs e)
		{
			base.OnClosed(e);
			m_Client.Leave(pokerTable.View.TableName);
			m_Client.LeaveTable(pokerTable.View.TableName);
			if (m_Client.LobbyForm.WindowState == FormWindowState.Minimized)
				m_Client.LobbyForm.WindowState = FormWindowState.Normal;
			m_Client.LobbyForm.TopMost = true;
			m_Client.LobbyForm.TopMost = false;
		}

		private void tbMessage_KeyPress(object sender, KeyPressEventArgs e)
		{
			if (e.KeyChar == 13)
			{
				if (!string.IsNullOrWhiteSpace(tbMessage.Text))
				{
					m_Client.SendChatMessage(pokerTable.View.TableName, tbMessage.Text.Trim());
					tbMessage.Text = "";
					e.Handled = true;
				}
			}
		}

		private void cbSitOut_CheckedChanged(object sender, EventArgs e)
		{
			if (cbSitOut.Checked)
				m_Client.SitOut(pokerTable.View.TableName);
			else
				m_Client.Waiting(pokerTable.View.TableName);
		}

		private void tbValue_Scroll(object sender, EventArgs e)
		{
			PokerCurrency currency = PokerCurrency.GetCurrency(pokerTable.View.Currency);
			tbAmount.Text = currency.ToString((ulong)tbValue.Value, false);
		}

		private void tbAmount_TextChanged(object sender, EventArgs e)
		{
			try
			{
				PokerCurrency currency = PokerCurrency.GetCurrency(pokerTable.View.Currency);
				int value = (int)(double.Parse(tbAmount.Text, CultureInfo.InvariantCulture) * Math.Pow(10, currency.PowerBase));
				tbValue.Value = value;
				bRaise.Text = "Raise (" + currency.ToString((ulong)tbValue.Value) + ")";
			}
			catch { }
			if ((int)AllInAmount == tbValue.Value)
				bRaise.Text = "All-In";
		}

		private void tbAmount_KeyPress(object sender, KeyPressEventArgs e)
		{
			if (e.KeyChar == 13)
			{
				bRaise.PerformClick();
				e.Handled = true;
			}
		}

		private void PokerClientForm_KeyPress(object sender, KeyPressEventArgs e)
		{
			e.Handled = false;
			if(!tbAmount.Focused && !tbMessage.Focused)
			{
				if (e.KeyChar == 'z' && bCall.Visible && bCall.Enabled)
					bCall.PerformClick();
				else if (e.KeyChar == 'a' && bFold.Visible && bFold.Enabled)
					bFold.PerformClick();
				else if (e.KeyChar == 'e' && bRaise.Visible && bRaise.Enabled)
					bRaise.PerformClick();
			}
		}

		private void pokerTable_ClickSeat(PokerTableControl.ClickSeatEventArgs e)
		{
			if (pokerTable.View != null && pokerTable.View.IsCashGame)
			{
				m_Client.AskBuyIn(pokerTable.View.TableName, e.Index);
			}
		}

		private void pokerTable_ClickMySeat(PokerTableControl.ClickSeatEventArgs e)
		{
			if (pokerTable.View != null && pokerTable.View.IsCashGame)
			{
				PokerTableView.PokerTableSeatView seat = pokerTable.View.Seats[e.Index];
				if (seat != null && seat.State == PokerSeatState.SittingOut)
				{
					SitInCashGameForm sitInCashGame = new SitInCashGameForm();
					sitInCashGame.Text = "Re-buy";
					sitInCashGame.Currency = PokerCurrency.GetCurrency(PokerTable.View.Currency);
					sitInCashGame.Stack = seat.Stack;
					if (sitInCashGame.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
					{
						m_Client.ReBuy(pokerTable.View.TableName, sitInCashGame.Amount);
					}
				}
			}
		}

		void pokerTable_ClickCard(PokerTableControl.ClickCardEventArgs e)
		{
			if (pokerTable.View != null)
			{
				if ((ModifierKeys & Keys.Control) == Keys.Control)
				{
					PokerTableView.PokerTableSeatView seat = pokerTable.View.Seats[e.Index];
					if (seat != null && seat.Name == m_Client.Login)
						m_Client.ShowCard(pokerTable.View.TableName, new Dll.Cards.CardList(e.Card));
				}
			}
		}

		private void bMuck_Click(object sender, EventArgs e)
		{
			m_Client.SendActionShow(pokerTable.View.TableName, false);
			SetShowHideCardsVisible(false);
			if (TimerThread != null)
				TimerThread.Abort();
		}

		private void bShows_Click(object sender, EventArgs e)
		{
			m_Client.SendActionShow(pokerTable.View.TableName, true);
			SetShowHideCardsVisible(false);
			if (TimerThread != null)
				TimerThread.Abort();
		}

		public void SetSeatTimer(int seatIndex, int timeOut)
		{
			if (SeatTimerThread != null)
				SeatTimerThread.Abort();
			pokerTable.SeatStartTime = DateTime.Now;
			DateTime end = pokerTable.SeatEndTime = pokerTable.SeatStartTime.AddMilliseconds(timeOut);
			Thread refreshThread = new Thread(delegate()
			{
				try
				{
					while (DateTime.Now.CompareTo(end) < 0 && pokerTable.View.CurrentAction == seatIndex)
					{
						Thread.Sleep(1000);
						pokerTable.Refresh();
					}
				}
				catch
				{

				}
				pokerTable.SeatEndTime = DateTime.MinValue;
				pokerTable.SeatStartTime = DateTime.MinValue;
				SeatTimerThread = null;
			});
			SeatTimerThread = refreshThread;
			refreshThread.Start();
		}

		public void WriteChat(string playerName, string message)
		{
			WriteLine(string.Format("{0}: {1}", playerName, message));
			PokerTable.Say(playerName, message);
		}


		public bool DoAutoAction()
		{
			if (IsAutoCall)
			{
				bCall_Click(null, EventArgs.Empty);
				UncheckAutoActions(false);
				return true;
			}
			else if (IsAutoFold)
			{
				bFold_Click(null, EventArgs.Empty);
				UncheckAutoActions(false);
				return true;
			}
			return false;
		}

		public void UncheckAutoActions(bool excludeFold)
		{
			cbCall.Checked = false;
			if(!excludeFold)
				cbFold.Checked = false;
		}

		public void BlindGoesUp(ulong smallBlind, ulong bigBlind, ulong ante)
		{
			pokerTable.BlindGoesUp(smallBlind, bigBlind, ante);
		}

		public bool SitOutChecked { get { return cbSitOut.Checked; } set { cbSitOut.Checked = value; } }

		public void SetAutoPostActionControlVisible(bool visible)
		{
			cbWait.Visible = visible;
		}

		public void SetPostActionControlVisible(bool visible)
		{
			PokerCurrency currency = PokerCurrency.GetCurrency(pokerTable.View.Currency);
			bWait.Visible = visible;
			bPost.Visible = visible;
			if(visible)
				bPost.Text = "Post (" + currency.ToString(pokerTable.View.BigBlind) + ")";
		}

		private void bPost_Click(object sender, EventArgs e)
		{
			m_Client.SendActionPost(pokerTable.View.TableName, true);
			SetPostActionControlVisible(false);
			if (TimerThread != null)
				TimerThread.Abort();
		}

		private void bWait_Click(object sender, EventArgs e)
		{
			m_Client.SendActionPost(pokerTable.View.TableName, false);
			SetPostActionControlVisible(false);
			if (TimerThread != null)
				TimerThread.Abort();
		}

		private void bLeave_Click(object sender, EventArgs e)
		{
			m_Client.TournamentRebuy(PokerTable.View.TournamentName, 0);
			SetRebuyControlVisible(false);
		}

		private void bRebuy_Click(object sender, EventArgs e)
		{
			m_Client.TournamentRebuy(PokerTable.View.TournamentName, 1);
			SetRebuyControlVisible(false);
		}

		private void bDoubleRebuy_Click(object sender, EventArgs e)
		{
			m_Client.TournamentRebuy(PokerTable.View.TournamentName, 2);
			SetRebuyControlVisible(false);
		}
	}
}
